package com.lucy.starter.aspect;

import cn.hutool.core.lang.Validator;
import cn.hutool.extra.servlet.ServletUtil;
import com.lucy.starter.anno.FormLock;
import com.lucy.starter.constant.HttpStatus;
import com.lucy.starter.exception.BusinessException;
import com.lucy.starter.loader.AuthService;
import com.lucy.starter.redis.RedisCache;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * @author kindear
 */
@Slf4j
@Aspect
@Component
@ConditionalOnClass(RedisCache.class)
public class FormLockAspect {
    /**
     * 引入Redis 服务
     */
    @Autowired
    RedisCache redisCache;
    /**
     * 引入鉴权系统服务
     */
    @Autowired
    AuthService authService;

    /**
     * 以自定义注解作为切入
     */
    @Pointcut("@annotation(com.lucy.starter.anno.FormLock)")
    public void FormLock(){}

    @Before("FormLock()")
    public void doBefore(JoinPoint joinPoint) {
        //获取当前请求对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        // 获取自定义注解信息
        FormLock formLock = method.getAnnotation(FormLock.class);
        // 获取锁定 前缀
        String key = formLock.key();
        if (Validator.isEmpty(key)){
            key = formLock.value();
        }
        // 锁定时长 单位 s
        int sec = formLock.sec();

        // 判断登录态
        Boolean isLogin = authService.isLogin();
        // 如果是登录态根据 token 拦截
        if (isLogin){
            // 获取当前登录用户ID
            String loginId = authService.getUserId();
            Boolean isLocked = redisCache.getCacheObject(key+":"+loginId);
            // 锁定
            if (Validator.isNotEmpty(isLocked)){
                throw new BusinessException(HttpStatus.FORBIDDEN,"请不要重复请求");
            }else {
                redisCache.setCacheObject(key+":"+loginId, true, sec, TimeUnit.SECONDS);
            }
        }else {
            String clientIp = ServletUtil.getClientIP(request);
            Boolean isLocked = redisCache.getCacheObject(key+":"+clientIp);
            if (Validator.isNotEmpty(isLocked)){
                throw new BusinessException(HttpStatus.FORBIDDEN,"请不要重复请求");
            }else {
                redisCache.setCacheObject(key+":"+clientIp, true, sec, TimeUnit.SECONDS);
            }
        }
    }

}
